<?php

require_once dirname(__FILE__) . '/app/Util/DbHandler.php';
require_once dirname(__FILE__) . '/app/Util/PassHash.php';
require_once dirname(__FILE__) . '/app/Util/UtilApi.php';
require_once dirname(__FILE__) . '/app/Common/Const.php';
require '.././libs/Slim/Slim.php';

\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim();

// User id from db - Global Variable
$user_id = null;
defined('BASE_PATH') || define('BASE_PATH', realpath(dirname(__FILE__) . '/../'));

/**
 * Adding Middle Layer to authenticate every request
 * Checking if the request has valid api key in the 'Authorization' header
 * @return type Description
 */
function authenticate(\Slim\Route $route) {
    // Getting request headers
    $headers = apache_request_headers();
    $app = \Slim\Slim::getInstance();

    // Verifying Authorization Header
    if (isset($headers['Authorization'])) {
        $db = new DbHandler();
        // get the api key
        $api_token = $headers['Authorization'];
        // validating api key
        if (!$db->isValidApiToken($api_token)) {
            // api key is not present in users table
            UtilApi::setOutputApi(API_STATUS_401, ACCESSS_DENIED, API_MSG_011);
            $app->stop();
        } else {
            global $user_id;
            // get user primary key id
            $user_id = $db->getUserIdByToken($api_token);
        }
    } else {
        // api key is missing in header
        UtilApi::setOutputApi(API_STATUS_400, AUTHENTICATE_MISSING, API_MSG_012);
        $app->stop();
    }
}

/**
 * User Registration
 * url - /register
 * method - POST
 * params - name, email, password
 */
$app->post('/register', function() use ($app) {
    // check for required params
    UtilApi::verifyRequiredParams(array('email', 'password'));
    // reading post params
    $email = $app->request->post('email');
    $password = $app->request->post('password');

    // validating email address
    UtilApi::validateEmail($email);

    $db = new DbHandler();
    // Generating API key
    $api_key = UtilApi::generateApiKey();
    $res = $db->registerUser($email, $password, $api_key);

    if ($res == USER_CREATED_SUCCESSFULLY) {
        UtilApi::setOutputApi(API_STATUS_201, USER_CREATED_SUCCESSFULLY, API_MSG_006);
        //UtilApi::sentMailActive($email, $api_key);
    } else if ($res == USER_CREATE_FAILED) {
        UtilApi::setOutputApi(API_STATUS_200, USER_CREATE_FAILED, API_MSG_008);
    } else if ($res == USER_ALREADY_EXISTED) {
        UtilApi::setOutputApi(API_STATUS_200, USER_ALREADY_EXISTED, API_MSG_007);
    }
});

/**
 * User Login
 * url - /login
 * method - POST
 * params - email, password
 */
$app->post('/login', function() use ($app) {
    // check for required params
    UtilApi::verifyRequiredParams(array('email', 'password'));

    // reading post params
    $email = $app->request()->post('email');
    $password = $app->request()->post('password');

    $db = new DbHandler();
    // check for correct email and password
    if ($db->checkLogin($email, $password)) {
        // get the user by email
        $user = $db->getUserByEmail($email);

        if ($user != null) {
            UtilApi::setOutputApi(API_STATUS_200, LOGIN_SUCCESSFULLY, '', $user);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, LOGIN_FAILED, API_MSG_005);
        }
    } else {
        // user credentials are wrong
        UtilApi::setOutputApi(API_STATUS_200, LOGIN_FAILED, API_MSG_004);
    }
});


$app->post('/userPhoto', 'authenticate', function() use ($app) {

    require_once dirname(__FILE__) . '/app/Util/UploadFile.php';
    $upload = new UploadFile();
    $urlUpload = BASE_PATH . '/upload/';
    global $user_id;
    if ($upload->uploadFile($urlUpload)) {
        $db = new DbHandler();
        $ret = $db->updateUserPhoto($user_id, $upload->getFileName());
        if ($ret) {
            UtilApi::setOutputApi(API_STATUS_201, UPDATE_SUCCESSFULLY, API_MSG_044);
        } else {
            UtilApi::setOutputApi(API_STATUS_201, UPDATE_FAILED, API_MSG_045);
        }
    } else {

        UtilApi::setOutputApi(API_STATUS_201, UPDATE_FAILED, API_MSG_045);
    }
    /*

      if ($res == USER_CREATED_SUCCESSFULLY) {
      UtilApi::setOutputApi(API_STATUS_201, USER_CREATED_SUCCESSFULLY, API_MSG_006);
      //UtilApi::sentMailActive($email, $api_key);
      } else if ($res == USER_CREATE_FAILED) {
      UtilApi::setOutputApi(API_STATUS_200, USER_CREATE_FAILED, API_MSG_008);
      } else if ($res == USER_ALREADY_EXISTED) {
      UtilApi::setOutputApi(API_STATUS_200, USER_ALREADY_EXISTED, API_MSG_007);
      } */
});

// User group
$app->group('/user', function () use ($app) {

    /**
     * Creat user
     * url - /user/create
     * method - POST
     * params
     */
    $app->post('/create', function() use ($app) {
        // check for required params
        UtilApi::verifyRequiredParams(array('facebookid', 'email'));

        // reading post params
        $email = $app->request->post('email');
        $facebookId = $app->request->post('facebookid');
        $city = $app->request->post('city');
        $photo = $app->request->post('photo');
        $longtitude = $app->request->post('longtitude');
        $lattitude = $app->request->post('lattitude');
        $dob = $app->request->post('dob');
        $sex = $app->request->post('sex');
        $allowAdult = $app->request->post('allowadult');
        $cpf = $app->request->post('cpf');
        $firstName = $app->request->post('fname');
        $lastName = $app->request->post('lname');
        $userphoto = $app->request->post('userphoto');
        $password = $app->request->post('password');


        // validating email address
        UtilApi::validateEmail($email);
        // validate paramts
        if ($longtitude != '') {
            UtilApi::validateDouble($longtitude, 'longtitude');
        }
        if ($lattitude != '') {
            UtilApi::validateDouble($lattitude, 'lattitude');
        }
        if ($sex != '') {
            UtilApi::validateInt($sex, 'sex');
        }
        if ($allowAdult != '') {
            UtilApi::validateInt($allowAdult, 'allowadult');
        }

        $db = new DbHandler();
        $res = $db->createUser($facebookId, $email, $password, $city, $photo, $longtitude, $lattitude, $dob, $sex, $allowAdult, $cpf, $firstName, $lastName, $userphoto);

        if ($res == USER_CREATED_SUCCESSFULLY) {
            UtilApi::setOutputApi(API_STATUS_201, USER_CREATED_SUCCESSFULLY, API_MSG_006);
        } else if ($res == USER_CREATE_FAILED) {
            UtilApi::setOutputApi(API_STATUS_200, USER_CREATE_FAILED, API_MSG_008);
        } else if ($res == USER_ALREADY_EXISTED) {
            UtilApi::setOutputApi(API_STATUS_200, USER_ALREADY_EXISTED, API_MSG_007);
        } else if ($res == FACEBOOKID_ALREADY_EXISTED) {
            UtilApi::setOutputApi(API_STATUS_200, FACEBOOKID_ALREADY_EXISTED, API_MSG_017);
        }
    });

    /**
     * return user information with the userID
     * method GET
     * url /user          
     */
    $app->get('/info/:id', function($userId) {

        $db = new DbHandler();
        // Fetching all user
        $user = $db->getUserById($userId);
        if ($user != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $user);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_013);
        }
    });

    /**
     * return user information with the userID
     * method GET
     * url /user          
     */
    $app->get('/validate/:token', function($token) {

        $db = new DbHandler();
        // fetching all user
        $res = $db->activeUserByToken($token);
        if ($res) {
            UtilApi::setOutputApi(API_STATUS_200, USER_ACTIVED, API_MSG_036);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, USER_INACTIVE, API_MSG_026);
        }
    });

    /**
     * Update user location
     * method PUT
     * url /userloction
     *
     */
    $app->put('/location/', 'authenticate', function() use($app) {

        // check for required params
        UtilApi::verifyRequiredParams(array('longtitude', 'lattitude'));

        global $user_id; 
        $longtitude = $app->request->put('longtitude');
        $lattitude = $app->request->put('lattitude');
        // validating location
        UtilApi::validateDouble($longtitude, 'longtitude');
        UtilApi::validateDouble($lattitude, 'lattitude');

        $db = new DbHandler();

        // updating task
        $result = $db->updateUserLocation($user_id, $longtitude, $lattitude);

        if ($result) {
            // User updated successfully
            UtilApi::setOutputApi(API_STATUS_200, UPDATE_SUCCESSFULLY, API_MSG_014);
        } else {
            // user failed to update
            UtilApi::setOutputApi(API_STATUS_200, UPDATE_FAILED, API_MSG_015);
        }
    });
});

// Device group
$app->group('/device', function () use ($app) {

    /**
     * Creating new device
     * method POST
     * @param string token
     * @param string systemos type os
     * url - /device/create
     */
    $app->post('/create', 'authenticate', function() use ($app) {
        // check for required params
        UtilApi::verifyRequiredParams(array('token', 'systemos'));
        $token = $app->request->post('token');
        $systemos = $app->request->post('systemos');

        global $user_id;
        $db = new DbHandler();
        // creating new device
        $result = $db->createDevice($user_id, $token, $systemos);

        if ($result == CREATED_SUCCESSFULLY) {
            UtilApi::setOutputApi(API_STATUS_201, CREATED_SUCCESSFULLY, API_MSG_009);
        } else {
            UtilApi::setOutputApi(API_STATUS_400, CREATE_FAILED, API_MSG_010);
        }
    });

    /**
     * Updating existing device
     * method PUT
     * params token, systemos
     * url - /device/:id
     */
    $app->put('/:id', 'authenticate', function($device_id) use($app) {

        // check for required params
        UtilApi::verifyRequiredParams(array('token', 'systemos'));

        global $user_id;
        // put Params
        $token = $app->request->put('token');
        $systemos = $app->request->put('systemos');

        $db = new DbHandler();
        // updating task
        $result = $db->updateDevice($user_id, $token, $systemos, $device_id);

        if ($result) {
            // task updated successfully
            UtilApi::setOutputApi(API_STATUS_200, UPDATE_SUCCESSFULLY, API_MSG_019);
        } else {
            // task failed to update
            UtilApi::setOutputApi(API_STATUS_200, UPDATE_FAILED, API_MSG_020);
        }
    });
});

// Tickets group
$app->group('/tickets', function () use ($app) {

    /**
     * Creating new tickets
     * method POST
     * @param int partyId
     * @param int ownerID
     * @param int priceCatId
     * url - /tickets/create
     */
    $app->post('/create', 'authenticate', function() use ($app) {
        // check for required params
        UtilApi::verifyRequiredParams(array('partyid', 'ownerid', 'pricecatid'));
        $partyId = $app->request->post('partyid');
        $ownerId = $app->request->post('ownerid');
        $priceCatId = $app->request->post('pricecatid');

        if ($partyId != '') {
            UtilApi::validateInt($partyId, 'PartyId');
        }
        if ($ownerId != '') {
            UtilApi::validateInt($ownerId, 'OwnerId');
        }
        if ($priceCatId != '') {
            UtilApi::validateInt($priceCatId, 'PriceCatID');
        }

        $db = new DbHandler();
        if (!$db->isPartyExists($partyId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_023);
            $app->stop();
        }
        if (!$db->isTicketCatExists($priceCatId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_025);
            $app->stop();
        }
        if (!$db->isUserExistsById($ownerId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_026);
            $app->stop();
        }
        // creating new device
        $result = $db->createTicket($partyId, $ownerId, $priceCatId);

        if ($result == CREATE_FAILED) {
            UtilApi::setOutputApi(API_STATUS_400, CREATE_FAILED, API_MSG_022);
        } else {
            UtilApi::setOutputApi(API_STATUS_201, CREATED_SUCCESSFULLY, API_MSG_021, $result);
        }
    });

    /**
     * Consume tickets
     * method PUT
     * params 
     * url - /tickets/consume
     */
    $app->put('/consume', 'authenticate', function() use($app) {

        // check for required params
        UtilApi::verifyRequiredParams(array('ticketcode', 'consumeuserid', 'receptionistid'));
        $ticketCode = $app->request->put('ticketcode');
        $consumeUserId = $app->request->put('consumeuserid');
        $receptionistId = $app->request->put('receptionistid');

        if ($receptionistId != '') {
            UtilApi::validateInt($receptionistId, 'ReceptionistId');
        }
        if ($consumeUserId != '') {
            UtilApi::validateInt($consumeUserId, 'ConsumeUserId');
        }
        $db = new DbHandler();
        if (!$db->isTicketExits($ticketCode)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_033);
            $app->stop();
        }
        if (!$db->isReceptoinistExists($receptionistId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_032);
            $app->stop();
        }
        if (!$db->isUserExistsById($consumeUserId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_031);
            $app->stop();
        }
        // creating new device
        $result = $db->consumeTicket($ticketCode, $consumeUserId, $receptionistId);

        if ($result == CONSUME_FAILED) {
            UtilApi::setOutputApi(API_STATUS_400, CONSUME_FAILED, API_MSG_035);
        } else {
            UtilApi::setOutputApi(API_STATUS_201, CONSUME_SUCCESSFULLY, API_MSG_034, $result);
        }
    });

    // Update Tickets with ID
    $app->put('/update/:id', 'authenticate', function($ticketId) use($app) {
        // check for required params
        UtilApi::verifyRequiredParams(array('partyid', 'ownerid', 'pricecatid'));
        $partyId = $app->request->post('partyid');
        $ownerId = $app->request->post('ownerid');
        $priceCatId = $app->request->post('pricecatid');
        if ($partyId != '') {
            UtilApi::validateInt($partyId, 'PartyId');
        }
        if ($ownerId != '') {
            UtilApi::validateInt($ownerId, 'OwnerId');
        }
        if ($priceCatId != '') {
            UtilApi::validateInt($priceCatId, 'PriceCatID');
        }

        $db = new DbHandler();
        if (!$db->isPartyExists($partyId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_023);
            $app->stop();
        }
        if (!$db->isTicketCatExists($priceCatId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_025);
            $app->stop();
        }
        if (!$db->isUserExistsById($ownerId)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_026);
            $app->stop();
        }
        // creating new device
        $result = $db->updateTicket($partyId, $ownerId, $priceCatId, $ticketId);

        if ($result == UPDATE_FAILED) {
            UtilApi::setOutputApi(API_STATUS_400, UPDATE_FAILED, API_MSG_028);
        } else {
            UtilApi::setOutputApi(API_STATUS_201, UPDATE_SUCCESSFULLY, API_MSG_027, $result);
        }
    });
    // Validate ticket 
    $app->post('/validate', function() use ($app) {
        // check for required params
        UtilApi::verifyRequiredParams(array('ticketcode'));
        $db = new DbHandler();
        // fetching all user
        $ticketCode = $app->request->post('ticketcode');
        $ticket = $db->validateTicket($ticketCode);
        if ($ticket != null) {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_030, $ticket);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 0, API_MSG_029);
        }
    });

    /**
     * get tickets belong to an user
     * method GET
     * url /tickets/user/2
     *
     */
    $app->get('/user/:user_id', function ($user_id) {
        if ($user_id != '') {
            UtilApi::validateInt($user_id, 'userid');
        }
        $db = new DbHandler();
        if (!$db->isUserExistsById($user_id)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_031);
            $app->stop();
        }
        $result = $db->getTicketsByUser($user_id);
        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_041);
        }
    });
    /**
     * take to transefer ticke from an use to other
     * method POST
     * url /tickets/transfe
     */
    $app->post('/transfer', function() {
        $from_user = $app->request->post('from_user');
        $to_user = $app->request->post('to_user');
        $ticket_id = $app->request->post('ticket_id');

        UtilApi::verifyRequiredParams(array('from_user', 'to_user', 'ticket_id'));
        $from_user = $app->request->post('from_user');
        $to_user = $app->request->post('to_user');
        $ticket_id = $app->request->post('ticket_id');
        if ($from_user != '') {
            UtilApi::validateInt($from_user, 'fromuser');
        }
        if ($to_user != '') {
            UtilApi::validateInt($to_user, 'touser');
        }
        if ($ticket_id != '') {
            UtilApi::validateInt($ticket_id, 'ticketid');
        }

        $db = new DbHandler();
        if (!$db->isTicketByIdExits($ticket_id)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_033);
            $app->stop();
        }
        if (!$db->isUserExistsById($from_user)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_026);
            $app->stop();
        }
        if (!$db->isUserExistsById($to_user)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_026);
            $app->stop();
        }
        // creating new device
        $result = $db->InsetTransference($from_user, $to_user, $ticket_id);

        if ($result == TRANSFER_CREATED_SUCCESSFULLY) {
            UtilApi::setOutputApi(API_STATUS_201, TRANSFER_CREATED_SUCCESSFULLY, API_MSG_042);
        } else {
            UtilApi::setOutputApi(API_STATUS_400, TRANSFER_CREATED_FAILED, API_MSG_043);
        }
    });
});


$app->group('/parties', function () use ($app) {
    /**
     * get parties with category
     * method GET
     * url /parties/list/2
     *
     */
    $app->get('/list:id', function ($category_id) {
        UtilApi::validateRequired($category_id, 'categoryid');
        if ($category_id != '') {
            UtilApi::validateInt($category_id, 'categoryid');
        }
        if (!$db->isCategoryExists($category_id)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_024);
            $app->stop();
        }
        $db = new DbHandler();
        $result = $db->getPartiesByCategory($category_id);

        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_037);
        }
    });

    /**
     * get parties which is most wanted
     * method GET
     * url /parties/mostwanted
     */
    $app->get('/mostwanted', function () {
        $db = new DbHandler();
        $result = $db->getMostWantedParties();
        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_037);
        }
    });

    /**
     * validate party code
     * method POST
     * url /parties/validate
     *
     */
    $app->post('/validate', function () {
        UtilApi::verifyRequiredParams(array('partycode'));
        $db = new DbHandler();
        // fetching all user
        $partyCode = $app->request->post('partycode');

        if ($db->getValidPartyCode($partyCode)) {
            UtilApi::setOutputApi(API_STATUS_200, 0, API_MSG_038);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_039);
        }
    });
    /**
     * get next parties which occur in 2 day
     * method GET
     * url /parties/next
     *
     */
    $app->get('/next/', function () {
        $db = new DbHandler();
        $result = $db->getNextParties();
        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_040);
        }
    });
    /**
     * get parties which is most wanted
     * method GET
     * url /parties/promotion
     */
    $app->get('/promotion/', function () {
        $db = new DbHandler();
        $result = $db->getPromotionParties();
        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_037);
        }
    });
    /**
     * Get
     * method GET
     * url /parties/users/3
     */
    $app->get('/users/:party_id', function ($party_id) {
        if ($party_id != '') {
            UtilApi::validateInt($party_id, 'partyid');
        }
        $db = new DbHandler();
        if (!$db->isPartyExists($party_id)) {
            UtilApi::setOutputApi(API_STATUS_400, VALIDATE_PARAMS, API_MSG_023);
            $app->stop();
        }
        $result = $db->getUsersInParty();
        if ($result != null) {
            UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
        } else {
            UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_040);
        }
    });
});
$app->group('/receptionist', function () use ($app) {

});
/**
   * get all categories
   * method GET
   * url /categories
   *
 */
$app->get('/categories', function() use ($app) {
    $db = new DbHandler();
    $result = $db->getCategories();
    if ($result != null) {
        UtilApi::setOutputApi(API_STATUS_200, '', '', $result);
    } else {
        UtilApi::setOutputApi(API_STATUS_200, 1, API_MSG_040);
    }
});

$app->run();
?>